package avicit.bdp.dds.api.controller;

import avicit.bdp.common.dto.response.dds.ProcessDefinitionDTO;
import avicit.bdp.common.service.dto.CommonTypeDTO;
import avicit.bdp.dds.api.dto.ProcessNodeDto;
import avicit.bdp.dds.api.enums.ComputingEngineEnum;
import avicit.bdp.dds.api.job.BdpDdsJob;
import avicit.bdp.dds.api.service.ProcessDefinitionService;
import avicit.bdp.dds.api.service.ProcessInstanceService;
import avicit.bdp.dds.api.service.TaskInstanceService;
import avicit.bdp.dds.api.service.TaskNodesService;
import avicit.bdp.dds.common.utils.ParameterUtils;
import avicit.bdp.dds.dao.entity.ProcessDefinition;
import avicit.bdp.dds.dao.entity.TaskInstance;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.rest.msg.QueryRespBean;
import avicit.platform6.core.rest.msg.ResponseMsg;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import springfox.documentation.annotations.ApiIgnore;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * 数据开发REST接口
 */
@RestController
@Api(tags = "数据开发REST接口")
@RequestMapping("/api/bdp/dds/dataDev")
public class DataDevRest {

    @Autowired
    private TaskInstanceService taskInstanceService;
    @Autowired
    private ProcessDefinitionService processDefinitionService;
    @Autowired
    private ProcessInstanceService processInstanceService;
    @Autowired
    private TaskNodesService taskNodesService;
    @Autowired
    private BdpDdsJob bdpDdsJob;

    /**
     * 获取任务进度
     */
    @ApiOperation(value = "任务进度")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "流程实例id", dataType = "String"),
            @ApiImplicitParam(name = "processDefinitionId", value = "流程定义id", dataType = "String")
    })
    @GetMapping("/getTaskProcess")
    public ResponseMsg<List<TaskInstance>> getTaskProcess(@RequestParam(value = "id", required = false) String id,
                                                          @RequestParam(value = "processDefinitionId", required = false) String processDefinitionId) {
        ResponseMsg<List<TaskInstance>> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(taskInstanceService.getTaskProcess(id, processDefinitionId));
        return responseMsg;
    }

    /**
     * 获取节点任务进度
     */
    @ApiOperation(value = "点任务进度")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "流程实例id", dataType = "String"),
            @ApiImplicitParam(name = "processDefinitionId", value = "流程定义id", dataType = "String")
    })
    @GetMapping("/getFlowTaskProcess")
    public ResponseMsg<Map<String, Object>> getFlowTaskProcess(@RequestParam(value = "id", required = false) String id,
                                                               @RequestParam(value = "processDefinitionId", required = false) String processDefinitionId) {
        ResponseMsg<Map<String, Object>> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(taskInstanceService.getFlowTaskProcess(id, processDefinitionId));
        return responseMsg;
    }

    /**
     * 启用/停用工作流
     *
     * @param processDefinition processDefinition
     * @return 启用/停用工作流结果
     */
    @ApiOperation(value = "启用/停用")
    @PostMapping("/execute")
    public ResponseMsg<Boolean> execute(@RequestBody ProcessDefinition processDefinition) {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(processDefinitionService.releaseProcessDefinition(
                processDefinition.getId(),
                processDefinition.getReleaseState()));
        return responseMsg;
    }

    /**
     * 按主键单条删除
     *
     * @param queryMap 主键id
     * @return ResponseMsg<Integer>
     */
    @ApiOperation(value = "按主键单条删除")
    @ApiImplicitParam(name = "id", value = "id", dataType = "String",  paramType = "body", required = true)
    @PostMapping("/deleteProcessById")
    public ResponseMsg<Integer> deleteProcessById(@ApiIgnore @RequestBody Map<String, String> queryMap) {
        ResponseMsg<Integer> responseMsg = new ResponseMsg<>();
        String id = queryMap.get("id");
        processDefinitionService.deleteProcessById(id);
        return responseMsg;
    }


    /**
     * 获取甘特图
     */
    @ApiOperation(value = "获取甘特图")
    @ApiImplicitParam(name = "id", value = "流程id", dataType = "String")
    @GetMapping("/getGantt")
    public ResponseMsg<Map<String, Object>> getGantt(@RequestParam String id) {
        ResponseMsg<Map<String, Object>> responseMsg = new ResponseMsg<>();
        Map<String, Object> result = processInstanceService.getGantt(id);
        responseMsg.setResponseBody(result);
        return responseMsg;
    }

    /**
     * 获取流程节点
     */
    @ApiOperation(value = "获取流程节点")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "数据空间id", dataType = "String"),
            @ApiImplicitParam(name = "id", value = "流程定义id", dataType = "String")
    })
    @GetMapping("/getProcessNode")
    public ResponseMsg<Map<String, List<ProcessNodeDto>>> getProcessNode(
            @RequestParam(value = "projectId", required = false) String projectId,
            @RequestParam(value = "id", required = false) String id) {
        ResponseMsg<Map<String, List<ProcessNodeDto>>> responseMsg = new ResponseMsg<>();
        if (StringUtils.isBlank(projectId)) {
            projectId = "-1";
        }
        Map<String, List<ProcessNodeDto>> result = taskNodesService.getProcessNode(projectId, id);
        responseMsg.setResponseBody(result);
        return responseMsg;
    }

    /**
     * 获取节点信息说明
     *
     * @param id 节点ID
     */
    @ApiOperation(value = "获取流程节点")
    @ApiImplicitParam(name = "id", value = "节点id", dataType = "String")
    @GetMapping("/getNodeInfoById")
    public ResponseMsg<ProcessNodeDto> getNodeInfoById(@RequestParam(value = "id") String id) {
        ResponseMsg<ProcessNodeDto> responseMsg = new ResponseMsg<>();
        ProcessNodeDto result = taskNodesService.getNodeInfoById(id);
        responseMsg.setResponseBody(result);
        return responseMsg;
    }


    /**
     * 创建数据开发
     *
     * @param processDefinition 流程定义
     * @return 流程定义ID
     */
    @PostMapping(value = "/insertDataDev")
    @ApiOperation(value = "创建数据开发")
    public ResponseMsg<String> insertDataDev(@RequestBody ProcessDefinition processDefinition) {
        if (processDefinition == null || processDefinition.getName() == null ||
                processDefinition.getTypeId() == null || processDefinition.getProjectId() == null) {
            throw new BusinessException("参数不能为空");
        }

        ResponseMsg<String> responseMsg = new ResponseMsg<>();
        //processDefinition.setType(2);
        processDefinition.setReleaseState(0);
        responseMsg.setResponseBody(processDefinitionService.createProcessDefinition(processDefinition));
        return responseMsg;
    }

    /**
     * verify process definition name unique
     *
     * @param projectId login user
     * @param typeId    project name
     * @param name      name
     * @return true if process definition name not exists, otherwise false
     */
    @ApiOperation(value = "verify-name", notes = "VERIFY_PROCESS_DEFINITION_NAME_NOTES")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "数据空间id", dataType = "String"),
            @ApiImplicitParam(name = "typeId", value = "分类id", dataType = "String"),
            @ApiImplicitParam(name = "name", value = "任务名称", dataType = "String"),
            @ApiImplicitParam(name = "type", value = "任务类型", dataType = "Int"),
            @ApiImplicitParam(name = "id", value = "流程定义id", dataType = "String")
    })
    @GetMapping(value = "/verifyName")
    public ResponseMsg<Boolean> verifyProcessDefinitionName(@RequestParam(value = "projectId") String projectId,
                                                            @RequestParam(value = "typeId") String typeId,
                                                            @RequestParam(value = "name") String name,
                                                            @RequestParam(value = "type") Integer type,
                                                            @RequestParam(value = "id", required = false) String id) {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        Boolean result = processDefinitionService.verifyProcessDefinitionName(projectId, typeId, name, type, id);
        responseMsg.setResponseBody(result);
        return responseMsg;
    }

    /**
     * 修改数据开发
     *
     * @param processDefinition 流程定义
     * @return 修改结果
     */
    @PostMapping(value = "/updateDataDev")
    @ApiOperation(value = "修改数据开发")
    public ResponseMsg<Boolean> updateDataDev(@RequestBody ProcessDefinition processDefinition) {
        if (processDefinition == null || StringUtils.isAnyBlank(processDefinition.getId(),
                processDefinition.getName(), processDefinition.getTypeId(), processDefinition.getProjectId())) {
            throw new BusinessException("参数不能为空");
        }

        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(processDefinitionService.updateProcessDefinition(processDefinition));
        return responseMsg;
    }

    /**
     * 删除数据开发
     *
     * @param processDefinitionId 流程定义ID
     * @return 删除结果
     */
    @ApiOperation(value = "删除数据开发")
    @ApiImplicitParam(name = "processDefinitionId", value = "流程定义id", dataType = "String")
    @GetMapping(value = "/deleteDataDev")
    public ResponseMsg<Boolean> deleteDataDev(@RequestParam("id") String processDefinitionId) {
        if (StringUtils.isBlank(processDefinitionId)) {
            throw new BusinessException("流程定义ID不能为空");
        }

        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(processDefinitionService.deleteProcessDefinitionById(processDefinitionId));
        return responseMsg;
    }


    /**
     * 分页查询数据开发列表
     *
     * @param typeId   分类ID
     * @param pageNo   page number
     * @param pageSize page size
     * @param keyWords 关键字
     * @return process definition page
     */
    @ApiOperation(value = "分页查询数据开发列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "typeId", value = "分类id", dataType = "String"),
            @ApiImplicitParam(name = "projectId", value = "数据空间id", dataType = "String"),
            @ApiImplicitParam(name = "type", value = "任务类型", dataType = "Int"),
            @ApiImplicitParam(name = "keyWords", value = "关键字", dataType = "String"),
            @ApiImplicitParam(name = "status", value = "任务状态", dataType = "Int"),
            @ApiImplicitParam(name = "pageNo", value = "当前页", dataType = "Int"),
            @ApiImplicitParam(name = "pageSize", value = "每页大小", dataType = "Int")
    })
    @GetMapping(value = "/getDataList")
    public ResponseMsg<QueryRespBean<ProcessDefinitionDTO>> getDataList(
            @RequestParam(value = "typeId") String typeId,
            @RequestParam(value = "projectId") String projectId,
            @RequestParam(value = "type") Integer type,
            @RequestParam(value = "keyWords", required = false) String keyWords,
            @RequestParam(value = "status", required = false) Integer status,
            @RequestParam("pageNo") Integer pageNo,
            @RequestParam("pageSize") Integer pageSize) {
        ResponseMsg<QueryRespBean<ProcessDefinitionDTO>> responseMsg = new ResponseMsg<>();

        keyWords = ParameterUtils.handleEscapes(keyWords);
        QueryRespBean<ProcessDefinitionDTO> queryRespBean = processDefinitionService.getDataList(
                typeId, projectId, type, keyWords, status, pageNo, pageSize);

        responseMsg.setResponseBody(queryRespBean);
        return responseMsg;
    }


    /**
     * 查询流程定义分类树
     *
     * @param projectId           projectId
     * @param processDefinitionId processDefinitionId
     * @return 流程定义分类树
     */
    @ApiOperation(value = "查询流程定义分类树")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "数据空间id", dataType = "String"),
            @ApiImplicitParam(name = "type", value = "任务类型", dataType = "Int"),
            @ApiImplicitParam(name = "processDefinitionId", value = "流程定义id", dataType = "String")
    })
    @GetMapping(value = "/getTypeAndProcessDefinitionList")
    public ResponseMsg<List<CommonTypeDTO>> getTypeAndProcessDefinitionList(
            @RequestParam(value = "projectId") String projectId,
            @RequestParam(value = "type") Integer type,
            @RequestParam(value = "processDefinitionId") String processDefinitionId) {

        if (StringUtils.isAnyBlank(projectId, processDefinitionId)) {
            throw new BusinessException("参数不能为空");
        }
        ResponseMsg<List<CommonTypeDTO>> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(processDefinitionService.getTypeAndProcessDefinitionList(
                projectId, type, processDefinitionId));
        return responseMsg;
    }

    /**
     * 查询执行引擎
     */
    @ApiOperation(value = "查询执行引擎")
    @GetMapping("/getComputingEngine")
    public ResponseMsg<List<String>> getComputingEngine() {
        ResponseMsg<List<String>> responseMsg = new ResponseMsg<>();
        List<String> list = new LinkedList<>();
        ComputingEngineEnum[] values = ComputingEngineEnum.values();
        for (ComputingEngineEnum value : values) {
            list.add(value.getName());
        }
        responseMsg.setResponseBody(list);
        return responseMsg;
    }

    /**
     * 测试统计任务
     */
    @GetMapping("/testJob")
    public ResponseMsg<Boolean> testJob() {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        try {
            bdpDdsJob.stateTaskCount();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return responseMsg;
    }

    /**
     * 根据发布状态查询树结构
     */
    @ApiOperation(value = "查询树结构")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "releaseState", value = "发布状态", dataType = "Int"),
            @ApiImplicitParam(name = "projectId", value = "数据空间id", dataType = "String"),
            @ApiImplicitParam(name = "type", value = "任务类型", dataType = "Int"),
            @ApiImplicitParam(name = "keyWords", value = "关键字", dataType = "String")
    })
    @GetMapping("/getDataDevList")
    public ResponseMsg<List<CommonTypeDTO>> getDataDevList(@RequestParam(value = "releaseState", required = false) Integer releaseState,
                                                           @RequestParam(value = "projectId") String projectId,
                                                           @RequestParam(value = "type") Integer type,
                                                           @RequestParam(value = "keyWords", required = false) String keyWords) {
        ResponseMsg<List<CommonTypeDTO>> responseMsg = new ResponseMsg<>();
        List<CommonTypeDTO> result = processDefinitionService.getDataDevList(releaseState, projectId, type, keyWords, "");
        responseMsg.setResponseBody(result);
        return responseMsg;
    }

    /**
     * 查询通用树
     */
    @ApiOperation(value = "查询树结构")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "数据空间id", dataType = "String"),
            @ApiImplicitParam(name = "type", value = "任务类型", dataType = "Int")
    })
    @GetMapping("/getDataDevTypeTree")
    public ResponseMsg<List<CommonTypeDTO>> getDataDevTypeTree(@RequestParam(value = "projectId") String projectId,
                                                               @RequestParam(value = "type") String type) {
        ResponseMsg<List<CommonTypeDTO>> responseMsg = new ResponseMsg<>();
        List<CommonTypeDTO> result = processDefinitionService.getDataDevTypeTree(projectId, type);
        responseMsg.setResponseBody(result);
        return responseMsg;
    }

    /**
     * 查询采集任务列表
     */
    @ApiOperation(value = "查询采集任务")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "数据空间id", dataType = "String"),
            @ApiImplicitParam(name = "type", value = "任务类型", dataType = "Int")
    })
    @GetMapping("/getDcsProcess")
    public ResponseMsg<List<ProcessDefinition>> getDcsProcess(@RequestParam(value = "projectId") String projectId,
                                                              @RequestParam(value = "type") Integer type) {
        ResponseMsg<List<ProcessDefinition>> responseMsg = new ResponseMsg<>();
        List<ProcessDefinition> result = processDefinitionService.getDcsProcess(projectId, type);
        responseMsg.setResponseBody(result);
        return responseMsg;
    }
}
